package com.zhangmeng.online.exam.ui.components;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.zhangmeng.online.exam.ui.utils.AlertUtils;
import com.zhangmeng.online.exam.ui.utils.ApiUtils;
import com.zhangmeng.online.exam.ui.utils.HttpUtils;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.VBox;

import java.util.*;

/**
 * 考试组件
 *
 * @author zm
 * @date 2025/3/20 16:29
 * @version: 1.0
 */
public class ExamComponent extends ScrollPane {

    //计数器
    private final SimpleIntegerProperty SINGLE_CHOICE_COUNT = new SimpleIntegerProperty(1);
    private final SimpleIntegerProperty MULTIPLE_CHOICE_COUNT = new SimpleIntegerProperty(1);
    private final SimpleIntegerProperty JUDGMENT_COUNT = new SimpleIntegerProperty(1);
    private final SimpleIntegerProperty NUMERICAL_COUNT = new SimpleIntegerProperty(1);
    private final SimpleIntegerProperty Fill_IN_THE_BLANKS_COUNT = new SimpleIntegerProperty(1);
    private final SimpleIntegerProperty SHORT_ANSWER_COUNT = new SimpleIntegerProperty(1);

    // 单选题
    private final ObservableList<SingleChoiceComponent> singleChoiceComponents = FXCollections.observableArrayList();
    // 多选题
    private final ObservableList<MultiChoiceComponent> multiChoiceComponents = FXCollections.observableArrayList();
    // 判断题
    private final ObservableList<TrueFalseComponent> judgmentComponents = FXCollections.observableArrayList();
    // 计算题
    private final ObservableList<NumericalComponent> numericalComponents = FXCollections.observableArrayList();
    // 填空题
    private final ObservableList<FillBlankComponent> fillInBlankComponents = FXCollections.observableArrayList();
    // 简答题
    private final ObservableList<ShortAnswerComponent> shortAnswerComponents = FXCollections.observableArrayList();

    private final SimpleIntegerProperty totalCount = new SimpleIntegerProperty(0);
    private final SimpleIntegerProperty totalIndex = new SimpleIntegerProperty(1);

    private VBox vBox;

    public ExamComponent(Map<String, Object> context) {

        this.vBox = new VBox(5);
        this.vBox.setPadding(new Insets(10));

        Map<String, Object> params = new HashMap<>();
        params.put("pageNum", ApiUtils.PAGE_NUM);
        params.put("pageSize", ApiUtils.PAGE_SIZE);
        params.put("id", context.get("paperId"));
        String userListData = HttpUtils.GET(ApiUtils.API_URL + "/paper/chooseQuestion/list", params);
        JSONObject jsonObject = JSON.parseObject(userListData);

        int code = jsonObject.getIntValue("code");
        if (code == 401){
            AlertUtils.alert_warning("请重新登录!");
            return;
        }

        JSONArray data = jsonObject.getJSONArray("data");
        int total = jsonObject.getIntValue("total");
        int index = 1;

        List<JSONObject> singleChoice_list = new ArrayList<>();
        List<JSONObject> multiChoice_list = new ArrayList<>();
        List<JSONObject> judgment_list = new ArrayList<>();
        List<JSONObject> numerical_list = new ArrayList<>();
        List<JSONObject> fillInBlank_list = new ArrayList<>();
        List<JSONObject> shortAnswer_list = new ArrayList<>();

        for (Object datum : data) {
            JSONObject question = (JSONObject) datum;
            String type = question.getString("type");

            switch (type) {
                case "单选题" -> singleChoice_list.add(question);
                case "多选题" -> multiChoice_list.add(question);
                case "判断题" -> judgment_list.add(question);
                case "计算题" -> numerical_list.add(question);
                case "填空题" -> fillInBlank_list.add(question);
                case "简答题" -> shortAnswer_list.add(question);
                default -> throw new IllegalStateException("Unexpected value: " + type);
            }
        }

        singleChoice_list.forEach(this::singleChoice);
        multiChoice_list.forEach(this::multiChoice);
        judgment_list.forEach(this::judgment);
        numerical_list.forEach(this::numerical);
        fillInBlank_list.forEach(this::fillInBlank);
        shortAnswer_list.forEach(this::shortAnswer);

        int count = singleChoiceComponents.size() + multiChoiceComponents.size() + judgmentComponents.size() + numericalComponents.size() + fillInBlankComponents.size() + shortAnswerComponents.size();
        totalCount.set(count);


//        Label label = new Label("一. 选择题");
//        label.setFont(new Font("黑体", 18));
//        this.vBox.getChildren().add(label);

        this.vBox.getChildren().addAll(singleChoiceComponents);
        this.vBox.getChildren().addAll(multiChoiceComponents);
        this.vBox.getChildren().addAll(judgmentComponents);
        this.vBox.getChildren().addAll(fillInBlankComponents);
        this.vBox.getChildren().addAll(shortAnswerComponents);
//        this.getChildren().addAll(numericalComponents);

        this.setContent(vBox);
        this.setFitToWidth(true);
        this.setFitToHeight(true);

    }

    public void scrollToIndex(int currentIndex) {
        Node node =  this.vBox.getChildren().get(currentIndex-1);
        scroll_to_bottom(node);
    }

    private void scroll_to_bottom(Node targetNode) {
        // 获取你要滚动到的特定标签，这里假设是第 25 个标签

        // 获取 VBox 在 ScrollPane 中的偏移量
        double targetNodeLayoutY = targetNode.getLayoutY();
        // 获取 VBox 的实际高度
        double vboxHeight = this.vBox.getHeight();
        // 获取 ScrollPane 的视口高度
        double scrollPaneViewportHeight = this.getViewportBounds().getHeight();
        // 计算需要的垂直滚动值，确保目标节点在视口中居中
        double vvalue = targetNodeLayoutY / (vboxHeight - scrollPaneViewportHeight);
        // 设置 ScrollPane 的垂直滚动值
        this.setVvalue(vvalue);
    }

    //简答题
    private void shortAnswer(JSONObject question) {
        SHORT_ANSWER_COUNT.set(totalIndex.get());
        String list = question.getString("options");
        List<Map> maps = JSONArray.parseArray(list, Map.class);
        List<Map<String, Object>> optionList = new ArrayList<>();
        for (Map map : maps) {
            boolean isAnswer = (boolean) map.get("isAnswer");
            Map<String, Object> option = new HashMap<>();
            option.put("id", map.get("id").toString());
            option.put("text", map.get("name").toString() + map.get("content").toString());
            option.put("isAnswer", isAnswer);
            option.put("option", map.get("name").toString().trim().replace(".", ""));
            option.put("content", map.get("content").toString());
            optionList.add(option);
        }
        ShortAnswerComponent shortAnswerComponent = new ShortAnswerComponent(SHORT_ANSWER_COUNT.get() + "." + question.getString("name"), optionList);
        Map<String, Object> context = new HashMap<>();
        context.put("question_id", question.getString("id"));
        context.put("paper_id", 1);
        shortAnswerComponent.setContext(context);
        shortAnswerComponents.add(shortAnswerComponent);
        SHORT_ANSWER_COUNT.set(SHORT_ANSWER_COUNT.get() + 1);
        totalIndex.set(totalIndex.get() + 1);
    }

    //填空题
    private void fillInBlank(JSONObject question) {
    }

    //计算题
    private void numerical(JSONObject question) {
    }

    //判断题
    private void judgment(JSONObject question) {
        JUDGMENT_COUNT.set(totalIndex.get());
        String list = question.getString("options");
        List<Map> maps = JSONArray.parseArray(list, Map.class);
        String correctAnswer = null;
        List<Map<String, Object>> optionList = new ArrayList<>();
        for (Map map : maps) {
            boolean isAnswer = (boolean) map.get("isAnswer");
            Map<String, Object> option = new HashMap<>();
            option.put("id", map.get("id").toString());
            option.put("text", map.get("name").toString() + map.get("content").toString());
            option.put("isAnswer", isAnswer);
            option.put("option", map.get("name").toString().trim().replace(".", ""));
            option.put("content", map.get("content").toString());
            optionList.add(option);
        }
        TrueFalseComponent trueFalseComponent = new TrueFalseComponent(JUDGMENT_COUNT.get() + "." + question.getString("name"), optionList);
        Map<String, Object> context = new HashMap<>();
        context.put("question_id", question.getString("id"));
        context.put("paper_id", 1);
        trueFalseComponent.setContext(context);
        judgmentComponents.add(trueFalseComponent);
        JUDGMENT_COUNT.set(JUDGMENT_COUNT.get() + 1);
        totalIndex.set(totalIndex.get() + 1);

    }

    //多选题
    private void multiChoice(JSONObject question) {

    }

    //单选题
    private void singleChoice(JSONObject question) {
        String list = question.getString("options");
        List<Map> maps = JSONArray.parseArray(list, Map.class);
        String correctAnswer = null;
        List<Map<String, Object>> optionList = new ArrayList<>();
        for (Map map : maps) {
            boolean isAnswer = (boolean) map.get("isAnswer");
            Map<String, Object> option = new HashMap<>();
            option.put("id", map.get("id").toString());
            option.put("text", map.get("name").toString() + map.get("content").toString());
            option.put("isAnswer", isAnswer);
            option.put("option", map.get("name").toString().trim().replace(".", ""));
            option.put("content", map.get("content").toString());
            optionList.add(option);
        }
        SingleChoiceComponent singleChoiceComponent = new SingleChoiceComponent(SINGLE_CHOICE_COUNT.get() + "." + question.getString("name"), optionList,SINGLE_CHOICE_COUNT.get());
        singleChoiceComponent.setCorrectAnswer(correctAnswer);
        Map<String, Object> context = new HashMap<>();
        context.put("question_id", question.getString("id"));
        context.put("paper_id", 1);
        singleChoiceComponent.setContext(context);
        singleChoiceComponents.add(singleChoiceComponent);
        SINGLE_CHOICE_COUNT.set(SINGLE_CHOICE_COUNT.get() + 1);
        totalIndex.set(totalIndex.get() + 1);
    }

    public int getTotalCount() {
        return totalCount.get();
    }

    public VBox getvBox() {
        return vBox;
    }

    public void setvBox(VBox vBox) {
        this.vBox = vBox;
    }

    public Node getNode(int index){
       return this.vBox.getChildren().get(index-1);
    }
}
